<?php

declare(strict_types=1);

namespace App\Service;

use App\Constants\ErrorCode;
use App\Exception\BusinessException;
use App\Library\Paybase;
use Hyperf\DbConnection\Db;
use Hyperf\HttpServer\Contract\RequestInterface;
use Yansongda\Pay\Exceptions\InvalidArgumentException;
use Yansongda\Pay\Exceptions\InvalidConfigException;
use Yansongda\Pay\Exceptions\InvalidSignException;
use Yansongda\Pay\Gateways\Alipay;
use Yansongda\Pay\Gateways\Wechat;
use Yansongda\Supports\Collection;
use Hyperf\Di\Annotation\Inject;

/**
 * 支付服务
 * Class PayService
 * @package App\Service
 */
class PayService
{

    const ADVANCE_PAY_ORDER = 1;
    const ADVANCE_PAY_INDUSTRY_CASH = 2;
    const ADVANCE_PAY_DADA = 3;

    /**
     * @Inject
     * @var DadaService
     */
    private $dada;

    /**
     * @Inject
     * @var AppUserService
     */
    private $appUser;

    /**
     * @Inject
     * @var RequestInterface
     */
    private $request;

    /**
     * @Inject
     * @var AdvancePayService
     */
    private $advancePay;

    /**
     * @Inject
     * @var Paybase
     */
    private $payBase;

    /**
     * @Inject
     * @var FlyPayOrderService
     */
    private $payOrder;

    /**
     * @Inject
     * @var FlyShopCashOrderService
     */
    private $cashOrder;

    /**
     * 支付单信息验证
     * @param array $params
     * @return array
     */
    public function payVerify(array $params): array
    {
        $return = [
            'msg' => '',
            'ret' => true,
            'data' => []
        ];
        $user_info = $this->appUser->getUserInfo($params['user_id']);
        if (empty($params['user_id']) || empty($params['order_sn']) || empty($params['pay_type']) || empty($params['pay_method']) || empty($params['type'])) {
            $return['msg'] = "缺少参数";
            $return['ret'] = false;
        } elseif (!in_array($params['pay_type'], ['alipay', 'wxpay'])) {
            $return['msg'] = "未知的支付类型";
            $return['ret'] = false;
        } elseif (empty($user_info)) {
            $return['msg'] = "用户未登录";
            $return['ret'] = false;
        }
        // 判断订单状态 :用户订单
        if ($params['type'] == 1) {
            $order = $this->payOrder->getPayOrderBySn($params['order_sn']);
        } elseif ($params['type'] == 2) {// 保证金订单
            $order = $this->cashOrder->getCashOrderBySn($params['order_sn']);
        } else {
            $order = $this->dada->getDadaWaitPayOrderBySn($params['order_sn']);
        }
        if (empty($order) || $order['is_pay'] != 0 || $order['paid_price'] > 0) {
            $return['msg'] = "订单状态异常";
            $return['ret'] = false;
        }
        if ($return['ret']) {
            $params['pay_price'] = $order['pay_price'];
            $params['pay_type'] = $params['pay_type'] == 'wxpay' ? "wechat" : $params['pay_type'];
            $params['auth_code'] = $params['auth_code'] ?? "";
            $params['openid'] = $user_info['mini_openid'];
            $params['return_url'] = $params['return_url'] ?? "";
            $return['data'] = $params;
        }
        return $return;
    }


    /**
     * 提交订单支付
     * @param array $params
     * @return false|string|Collection
     */
    public function submit(array $params)
    {

        if (empty($params['order_price'])) {
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '订单金额为0');
        }
        // 支付数据
        $submit_data = [
            'type' => $params['pay_type'],
            'order_id' => $this->advancePay->generateOuterSn($params),
            'title' => ($params['type'] == 1 ? "" : "(保证金订单)") . "订单编号：" . $params['order_sn'] . "支付",
            'amount' => $params['pay_price'],
            'method' => $params['pay_method'],
            'openid' => $params['openid'] ?? "",
            'auth_code' => $params['auth_code'] ?? "",
            'return_url' => $params['return_url'] ?? "",// 支付成功跳转地址
        ];
        return true;// todo 根据支付参数生成支付记录单
        // 唤起支付
        try {
            $res = $this->payBase->submitOrder($submit_data);
        } catch (\Throwable $exception) {
            echo $exception->getMessage();
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '支付失败');
        }
        return $res;
    }

    /**
     * 订单支付回调
     * @param string $pay_type
     * @param array|null $params
     * @return bool|Alipay|Wechat
     */
    public function notify(string $pay_type = "wechat", array $params = [])
    {
//        if (empty($params)) {
//            $params = $pay_type == "wechat" ? $this->request->getBody()->getContents() : $this->request->all();
//        }
        $pay_method = $params['paymethod'] ? $params['paymethod'] : "";
//        $pay_instance = $this->payBase->checkNotify($pay_type);
//        if (false === $pay_instance) {
//            echo "签名错误!";
//            return $pay_instance;
//        } else {
//            echo "签名成功!";
//        }
        try {
//            $data = $pay_instance->verify($params);
            $data = $params;// todo 模拟参数
            Db::beginTransaction();
            $outer_sn = $data['out_trade_no'];
            $advance_pay = $this->advancePay->getRecordByNotify($outer_sn, $pay_type, $pay_method);
            if (empty($advance_pay)) {
                echo "未获取到支付记录";
                return false;
            }
            switch ($advance_pay['type']) {
                case self::ADVANCE_PAY_ORDER:
                    // 用户订单(更新订单相关状态)
                    $this->payOrder->payOrderNotifyPay($advance_pay['order_sn'], $pay_type, $pay_method, $outer_sn);
                    break;
                case self::ADVANCE_PAY_INDUSTRY_CASH:
                    // 店铺保证金订单
                    $this->cashOrder->cashNotifyPay($advance_pay['order_sn'], $pay_type, $pay_method, $outer_sn);
                    break;
                case self::ADVANCE_PAY_DADA:
                    $this->dada->payNotify($advance_pay['order_sn'], $pay_type, $pay_method, $outer_sn);
                    break;
                default:
                    echo "未知支付来源";
                    return false;
                    break;
            }
        } catch (InvalidArgumentException $e) {
            Db::rollBack();
            echo $e->getMessage();
        } catch (InvalidConfigException $e) {
            Db::rollBack();
            echo $e->getMessage();
        } catch (InvalidSignException $e) {
            Db::rollBack();
            echo $e->getMessage();
        } catch (\Throwable $exception) {
            Db::rollBack();
            echo $exception->getMessage();
        }
        Db::commit();
        return true;
    }

    /**
     * 退款
     * @param string $pay_outer_sn
     * @param float $refund_amount
     * @return bool
     */
    public function refund(string $pay_outer_sn, float $refund_amount): bool
    {
        return true;
    }
}